﻿
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Media3D;

namespace LxCFD
{
    public class NSEquation : NSEquationBase     //注意求解顺序
    {
        public List<BoundaryFixValueWall> FixValueWallBounds = new List<BoundaryFixValueWall>();
        public List<BoundaryScalarSymmetry> SymmetryBounds = new List<BoundaryScalarSymmetry>();
        public List<BoundaryFlowValue> FlowValueBounds = new List<BoundaryFlowValue>();
        public List<BoundaryFixFlux> FluxBounds = new List<BoundaryFixFlux>();
        public List<BoundaryHeadBase> CoupledWalls = new List<BoundaryHeadBase>();

        protected ConvectionSchemes ConvectionScheme;
        #region 设置矩阵
        public void SetZone_CommonTerm(Value1Base<double> Gamma, ValueBase<double> S, Value1Base<double> iniValue, double relaxFactor)
        {
            clear_eFlags();
            FixValueWallBounds.Clear();
            SymmetryBounds.Clear();
            FlowValueBounds.Clear();
            FluxBounds.Clear();
            CoupledWalls.Clear();

            this.Gamma = Gamma;
            this.Source = S;
            this.IniValue = iniValue;
            this.RelaxFactor = relaxFactor;
        }
        public void SetZone_ConvTerm(Value1Base<double> Conv, ConvectionSchemes convectionScheme, MassFluxBase massBase)
        {
            this.Conv = Conv;
            this.ConvectionScheme = convectionScheme;
            switch (convectionScheme)
            {
                case ConvectionSchemes.MUSCL_DC:
                    if (!(CalgCfPhir is MUSCL_DC)) CalgCfPhir = new MUSCL_DC();
                    break;
                case ConvectionSchemes.OSHER_DC:
                    if (!(CalgCfPhir is OSHER_DC)) CalgCfPhir = new OSHER_DC();
                    break;
                default:
                    break;
            }
            this.MassFlux = massBase.MassFlux;
            this.MassImbalance = massBase.MassImbalance;
            this.VelocityDirectionCorrection = massBase.VelocityDirectionCorrection;
        }
        public void SetBoundary_fixValue(Value1Base<double> fixValue, FvThread thread)
        {
            BoundaryFixValueWall boundaryFixValue = new BoundaryFixValueWall();
            boundaryFixValue.SetHead(thread);
            boundaryFixValue.setFixValue(fixValue);

            FixValueWallBounds.Add(boundaryFixValue);
            e_FixValue.Add(thread.ID);
        }
        public void SetBoundary_symmetry(FvThread thread)
        {
            BoundaryScalarSymmetry boundarysymmetry = new BoundaryScalarSymmetry();
            boundarysymmetry.SetHead(thread);

            SymmetryBounds.Add(boundarysymmetry);
            e_ALUO0.Add(thread.ID);
        }
        public void SetBoundary_flow(Value1Base<double> baseValue, FvThread thread)
        {
            BoundaryFlowValue flow = new BoundaryFlowValue();
            flow.SetHead(thread);
            flow.setParameter(baseValue);

            FlowValueBounds.Add(flow);
            e_FixValue.Add(thread.ID);
        }
        public void SetBoundary_Coupled_Wall(FvThread thread)
        {
            BoundaryHeadBase wall = new BoundaryHeadBase();
            wall.SetHead(thread);

            CoupledWalls.Add(wall);
            e_Couple.Add(thread.ID);
        }
        #endregion
        #region 供外部调用的计算过程
        public override void Initialize()
        {
            MultiThreads.RunCalTasks(initialize);
        }
        public void initialize(int taskIndex)
        {
            set_x(IniValue, InnerIndex, taskIndex);
            Set_x_Bound(taskIndex);
            foreach (BoundaryScalarSymmetry b in SymmetryBounds)
            {
                set_x(IniValue, b.ThreadIndex, taskIndex);
            }
            foreach (var b in FlowValueBounds)
            {
                set_x(b.BaseValue, b.ThreadIndex, taskIndex);
            }
            foreach (var b in CoupledWalls)
            {
                set_x(IniValue, b.ThreadIndex, taskIndex);
            }
        }
        public override void Set_x_Bound(int taskIndex)
        {
            foreach (BoundaryFixValueWall b in FixValueWallBounds)
            {
                if (b.SetxState.GetIsNeedToCal(taskIndex))
                {
                    set_x(b.FixValue, b.ThreadIndex, taskIndex);
                }
            }
        }
        public override void SetAb_Step1(int taskIndex)
        {
            //计算内部面 A_LU
            switch (ConvectionScheme)
            {
                case ConvectionSchemes.FirstOrderUpwind:
                default:
                    set_Ab_Upwind_inner(taskIndex);
                    break;
                case ConvectionSchemes.SecondOrderUpwind:
                    set_Ab_SOU_inner(taskIndex);
                    break;
                case ConvectionSchemes.OSHER:
                    set_Ab_OSHER_inner(taskIndex);
                    break;
                case ConvectionSchemes.MUSCL:
                    set_Ab_MUSCL_inner(taskIndex);
                    break;
                case ConvectionSchemes.OSHER_DC:
                case ConvectionSchemes.MUSCL_DC:
                    set_Ab_TVD_DC_inner(taskIndex);
                    break;
            }
            //计算边界面的
            foreach (var b in FixValueWallBounds)
            {
                set_Ab_boundOwner_DiffPart(b.ThreadIndex, taskIndex);
            }
            foreach (var b in SymmetryBounds)
            {
                set_A_boundOwner_0(b.ThreadIndex, taskIndex);
            }
            foreach (var b in FlowValueBounds)
            {
                set_Ab_bound_flow(b.ThreadIndex, taskIndex);
            }
        }

        public override void SetAb_Step2(int taskIndex)
        {
            if (Source is Value1Base<double> source1)
            {
                setAb_step2(source1, taskIndex);
            }
            else if (Source is Value2Base<double> source2)
            {
                setAb_step2(source2, taskIndex);
            }
            else
            {
                LxConsole.Error("未知的源项类型");
            }
        }

        public override void Update_x_Bound(int taskIndex)
        {
            foreach (var b in SymmetryBounds)
            {
                updateBound_grad0(b.ThreadIndex, taskIndex);
            }
            foreach (var b in FlowValueBounds)
            {
                set_x_flow(b.BaseValue, b.ThreadIndex, taskIndex);
            }
        }
        #endregion

        public class BoundaryFixValueWall : BoundaryHeadBase
        {
            public Value1Base<double> FixValue;
            public ValueStateLog SetxState;
            public void setFixValue(Value1Base<double> fixValue)
            {
                this.FixValue = fixValue;
                SetxState = new ValueStateLog(fixValue.IsConstant() ) ;
            }
        }
        public class BoundaryScalarSymmetry : BoundaryHeadBase
        {
        }
        public class BoundaryFlowValue : BoundaryHeadBase
        {
            public Value1Base<double> BaseValue { get; set; }
            public void setParameter(Value1Base<double> baseValue)
            {
                this.BaseValue = baseValue;
            }
        }
        public class BoundaryFixFlux : BoundaryHeadBase
        {
            public Value1Base<double> Flux { get; set; }
            public void setParameter(Value1Base<double> flux)
            {
                this.Flux = flux;
            }
        }
    }
}
